package net.ufrog.common;

import net.ufrog.common.exception.ServiceException;
import net.ufrog.common.utils.Strings;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author ultrafrog
 * @version 1.0, 2014-12-08
 * @since 1.0
 */
public class GetterAndSetter {

    /** Getter */
    private Method getter;

    /** Setter */
    private Method setter;

    /**
     * 构造函数
     *
     * @param fieldName 字段名称
     * @param fieldType 字段类型
     * @param requiredType 请求类型
     */
    public GetterAndSetter(String fieldName, Class<?> fieldType, Class<?> requiredType) {
        try {
            this.setter = requiredType.getDeclaredMethod("set" + Strings.toTitleCase(fieldName), fieldType);
            if (fieldType == Boolean.class) {
                try {
                    this.getter = requiredType.getDeclaredMethod("is" + Strings.toTitleCase(fieldName));
                } catch (NoSuchMethodException e) {
                    Logger.debug("cannot find is%s by boolean field.", Strings.toTitleCase(fieldName));
                    this.getter = requiredType.getDeclaredMethod("get" + Strings.toTitleCase(fieldName));
                }
            } else {
                this.getter = requiredType.getDeclaredMethod("get" + Strings.toTitleCase(fieldName));
            }
        } catch (NoSuchMethodException | SecurityException e) {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * 构造函数
     *
     * @param getter getter
     * @param setter setter
     */
    public GetterAndSetter(Method getter, Method setter) {
        this.getter = getter;
        this.setter = setter;
    }

    /**
     * 执行方法
     *
     * @param obj 对象
     * @return 属性内容
     */
    public Object doGetter(Object obj) {
        try {
            return getter.invoke(obj);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new ServiceException("cannot do getter.", e);
        }
    }

    /**
     * 执行方法
     *
     * @param obj 对象
     * @param arg 参数
     */
    public void doSetter(Object obj, Object arg) {
        try {
            setter.invoke(obj, arg);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new ServiceException("cannot do setter.", e);
        }
    }
}
